﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Aim2.Screen {
    public class BackgroundScreen : GameScreen, IDisposable {

        /// <summary>
        /// The period of the parallax motion in the starfield.
        /// </summary>
        const float starsParallaxPeriod = 30f;


        /// <summary>
        /// The amplitude of the parallax motion in the starfield.
        /// </summary>
        const float starsParallaxAmplitude = 2048f;

        public static Background Background { get; set; }

        /// <summary>
        /// Persistent movement tracker, used to slightly parallax the stars.
        /// </summary>
        private double movement;


        #region Initialization Methods

        public BackgroundScreen() {
            TransitionOnTime = TimeSpan.FromSeconds(1.0);
            TransitionOffTime = TimeSpan.FromSeconds(1.0);
        }

        public override void LoadContent() {
            movement = 0f;

            Background = new Background(
                Vector2.Multiply(new Vector2(
                    (float)Math.Cos(movement / starsParallaxPeriod),
                    (float)Math.Sin(movement / starsParallaxPeriod)),
                    starsParallaxAmplitude),
                ScreenManager.GraphicsDevice, ScreenManager.Content);
            Background.LoadContent();

            base.LoadContent();
        }

        public override void UnloadContent() {
            if (Background != null) {
                Background.UnloadContent();
                Background = null;
            }

            base.UnloadContent();
        }


        #endregion


        #region Updating Methods


        /// <summary>
        /// Updates the background screen. Unlike most screens, this should not
        /// transition off even if it has been covered by another screen: it is
        /// supposed to be covered, after all! This overload forces the
        /// coveredByOtherScreen parameter to false in order to stop the base
        /// Update method wanting to transition off.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen) {
            if (Background != null) {
                Background.Update((float)gameTime.ElapsedGameTime.TotalSeconds);
            }
            base.Update(gameTime, otherScreenHasFocus, false);
        }


        #endregion


        #region Drawing Methods


        /// <summary>
        /// Draws the background screen.
        /// </summary>
        public override void Draw(GameTime gameTime) {
            if (Background != null) {
                // update the parallax movement
                movement += gameTime.ElapsedGameTime.TotalSeconds;
                Vector2 position = Vector2.Multiply(new Vector2(
                        (float)Math.Cos(movement / starsParallaxPeriod),
                        (float)Math.Sin(movement / starsParallaxPeriod)),
                        starsParallaxAmplitude);

                Background.Draw(position);
            }

        }


        #endregion


        #region IDisposable Implementation


        /// <summary>
        /// Finalizes the BackgroundScreen object, calls Dispose(false)
        /// </summary>
        ~BackgroundScreen() {
            Dispose(false);
        }


        /// <summary>
        /// Disposes the BackgroundScreen object.
        /// </summary>
        public void Dispose() {
            Dispose(true);
            GC.SuppressFinalize(this);
        }


        /// <summary>
        /// Disposes this object.
        /// </summary>
        /// <param name="disposing">
        /// True if this method was called as part of the Dispose method.
        /// </param>
        protected virtual void Dispose(bool disposing) {
            if (disposing) {
                lock (this) {
                    if (Background != null) {
                        Background.Dispose();
                        Background = null;
                    }
                }
            }
        }


        #endregion
    }
}
